import type { IDataItem, ICommoditySpecsItem } from './types';

// 邻接表
export class Graph {
  // 顶点
  public vertexs: string[]
  // 邻接表
  public adjoinArr: string[][]
  constructor(vertexs: string[]) {
    this.vertexs = vertexs
    this.adjoinArr = []
    this.init()
  }

  // 初始化 空邻接表
  init() {
    this.vertexs.forEach((v, i) => {
      this.adjoinArr[i] = []
    })
  }

  // 设置顶点的边
  setAdjoinArr(vertex: string, sides: string[]) {
    const pIndex = this.vertexs.indexOf(vertex)
    // 需要去重，并将顶点自身移除
    const set = new Set(this.adjoinArr[pIndex].concat(sides))
    set.delete(vertex)
    this.adjoinArr[pIndex] = Array.from(set)
  }

  // 测试 打印
  showVertexs() {
    console.log(this.adjoinArr)
  }

  // 交集， 同时包含
  getUnions(vertexArr: string[]) {
    const _vertexArr = vertexArr.filter(Boolean)
    // 取交集，每一项都包含于表种
    const unions = this.adjoinArr.reduce((resArr, curArr, idx) => {
      const isAllIncludes = _vertexArr.every(v => curArr.includes(v))
      if (isAllIncludes) {
        resArr.push(this.vertexs[idx])
      }
      return resArr
    }, [] as string[])
    return unions
  }

  // 并集， 包含即可
  getCollection(vertexArr: string[]) {
    const _vertexArr = vertexArr.filter(Boolean)
    // 取并集，则包含即可
    const collections = this.adjoinArr.reduce((resArr, curArr, idx) => {
      const isSomeIncludes = _vertexArr.some(v => curArr.includes(v))
      if (isSomeIncludes) {
        resArr.push(this.vertexs[idx])
      }
      return resArr
    }, [] as string[])
    return collections
  }
}

export class ShopAdjoin extends Graph {
  public commoditySpecs: ICommoditySpecsItem[] = []
  public data: IDataItem[] = []
  constructor(commoditySpecs: ICommoditySpecsItem[], data: IDataItem[]) {
    super(commoditySpecs.flatMap(v => v.list))

    this.commoditySpecs = commoditySpecs
    this.data = data
    // 单规格矩阵
    this.initCommodity()
    // 同类顶点创建
    this.initSimilar()
  }

  initCommodity() {
    this.data.forEach((item) => {
      this.applyCommodity(item.specs)
    })
  }
  applyCommodity(vertexArr: string[]) {
    vertexArr.forEach((vertex) => {
      this.setAdjoinArr(vertex, vertexArr)
    })
  }
  initSimilar() {
    // 初始所有可选规格
    const specsOption = this.getCollection(this.vertexs)
    this.commoditySpecs.forEach((item) => {
      const filterSpecs = item.list.filter(it => specsOption.includes(it))
      this.applyCommodity(filterSpecs)
    })
  }

  // 查询可选项
  querySpecsOptions(specs: string[]) {
    // 判断是否存在可选项 | 初始所有状态可选
    return specs.some(Boolean)
      ? this.getUnions(specs)
      : this.getCollection(this.vertexs)
  }
}
